﻿using AutoRegistDependency.Attributes;
using AutoRegistDependency.Interface;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Core.Helper;
using HandyControl.Controls;
using HandyControl.Data;
using HandyWpf.ViewModels.Base;
using HandyWpf.Views.Equ;
using Microsoft.Win32;
using Models.Entities;
using Models.Queries;
using Services.Base;
using Services.Equ;
using Services.Equ.PcapCommunication;
using Services.Equ.PcapCommunication.Abstract;
using Services.Equ.PcapCommunication.Operation;
using SharpPcap;
using SqlSugar;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq.Expressions;
using System.Net.NetworkInformation;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Threading;
using Wpf.Ui.Controls;
using MessageBoxButton = System.Windows.MessageBoxButton;
using MessageBoxResult = System.Windows.MessageBoxResult;

namespace HandyWpf.ViewModels
{
    [Component]
    public partial class EquInfoViewModel : BasePageCRUDViewModel<EquInfo, EquInfoQuery, IEquService, int, EquInfoForm>
    {
        private readonly IpHelper ipHelper;
        public EquInfoViewModel(IpHelper ipHelper, IEventBus eventBus, IBaseService<EquInfo> baseService) : base(eventBus, baseService)
        {
            InitDevice();
            this.ipHelper = ipHelper;
        }
        [ObservableProperty]
        private ObservableCollection<ILiveDevice> captureDeviceList = [];
        [ObservableProperty]
        private ILiveDevice? selectDevice;
        [ObservableProperty]
        private string? password;
        [ObservableProperty]
        private ObservableCollection<EquInfo> upgradeList=[];
        [ObservableProperty]
        private FileInfo? upgradeFile;
        [ObservableProperty]
        private string? startIP;
        public void InitDevice()
        {
            IEquService service = (IEquService)baseService;
            CaptureDeviceList.Clear();
            var list= service.GetDevices();
            foreach (var device in list)
            {
                CaptureDeviceList.Add(device);
            }
        }
        [RelayCommand]
        public void HandleRestart(string mac)
        {
            if (string.IsNullOrEmpty(Password))
            {
                Growl.Error("请先输入通讯密码！");
                return;
            }
            Loading = true;
            RestartCommunication restartCommunication = new(PhysicalAddress.Parse(mac), Password, SelectDevice);
            Dispatcher.CurrentDispatcher.Invoke(async () =>
            {
                var op = new PcapOperation<bool>(restartCommunication);
                var dic= await op.GetOperationResult();
                DispalyResult(dic,mac, "重启成功！", "重启失败！");
            });
        }
        [RelayCommand]
        public void PasswordChanged(object obj)
        {
            var passwordBox= (System.Windows.Controls.PasswordBox)obj;
            Password = passwordBox.Password;
        }
        [RelayCommand]
        public void SearchEqu()
        {
            Loading = true;
            IEquService service = (IEquService)baseService;
            var searcher = new SearchDeviceCommunication(SelectDevice);
            Dispatcher.CurrentDispatcher.Invoke(async () =>
            {
                var equList=await searcher.GetCommunicationResult();
                await baseService.AddAsync(equList);
                GetList();
                Loading = false;
            });

        }
        public override void FormEdit()
        {
            if (string.IsNullOrEmpty(Password))
            {
                Growl.Error("请先输入通讯密码");
                return;
            }
            if (ValidateNetworkinfo(Form))
            {
                EditNetworkInfoCommunication editNetworkInfoCommunication = new(PhysicalAddress.Parse(Form.Mac), Password, SelectDevice)
                {
                    EquInfo = new EquInfo()
                    {
                        Ip = Form.Ip,
                        Mask = Form.Mask,
                        GateWay = Form.GateWay,
                        Vlan = Form.Vlan ?? 0,
                    }
                };
                var op = new PcapOperation<bool>(editNetworkInfoCommunication);
                Dispatcher.CurrentDispatcher.Invoke(async () =>
                {
                    var dic = await op.GetOperationResult();
                    await baseService.UpdateAsync(Form);
                    DispalyResult(dic, Form.Mac, "修改网卡信息成功！", "修改网卡信息失败！");
                    this.GetList();
                });
                CloseCurrentPageDialog(typeof(EquInfoPage));
            }
        }
        private bool ValidateNetworkinfo(EquInfo equ)
        {
            bool valid = true;
            if (!ipHelper.ValidateIPAddress(equ.Ip))
            {
                valid = false;
                Growl.Error("设备ip格式不正确");
            }
            if (!ipHelper.ValidateIPAddress(equ.Mask))
            {
                valid = false;
                Growl.Error("设备掩码格式不正确");
            }
            if (!ipHelper.ValidateIPAddress(equ.GateWay))
            {
                valid = false;
                Growl.Error("设备网关格式不正确");
            }
            if(ipHelper.GetIpType(equ.Ip) != 2)
            {
                valid = false;
                Growl.Error("设备ip仅支持C类");
            }
            if (equ.Ip.EndsWith(".255") || equ.Ip.StartsWith(".0"))
            {
                valid = false;
                Growl.Error("设备ip的最后一位不能是0或者255！");
            }
            return valid;
        }
        [RelayCommand]
        public void HandleUpgrade(int id)
        {
            Form = GetEntityById(id);
            UpgradeList.Clear();
            UpgradeList.Add(Form);
            OpenCurrentPageDialog(typeof(UpgradeForm));
        }
        [RelayCommand]
        public void HandleBatchUpgrade()
        {
            GetSelectedValue();
            OpenCurrentPageDialog(typeof(UpgradeForm));
        }
        [RelayCommand]
        public void HandleUploadFile()
        {
            OpenFileDialog openFileDialog = new();
            if (openFileDialog.ShowDialog() == true)
            {
                string fileName=openFileDialog.FileName;
                UpgradeFile=new FileInfo(fileName);
            }
        }
        [RelayCommand]
        public void HandleUpgradeCommunication(string type)
        {
            foreach(var equ in UpgradeList)
            {
                List<AbstractPcapCommunication<bool>> abstractPcapCommunications = [];
                PhysicalAddress macAdress = PhysicalAddress.Parse(equ.Mac);
                AbstractPcapCommunication<bool> writeCommunication = new WriteCommnuication(macAdress, Password, SelectDevice);
                AbstractPcapCommunication<bool> writeFileCommunication = new WriteFileCommunication(UpgradeFile, macAdress, Password, SelectDevice);
                AbstractPcapCommunication<bool> writeCompleteCommunication = new WriteCompleteCommunication(UpgradeFile, macAdress, Password, SelectDevice);
                AbstractPcapCommunication<bool> finalCommnication = CommunicationFactory(type, macAdress, Password, SelectDevice);
                abstractPcapCommunications.Add(writeCommunication);
                abstractPcapCommunications.Add(writeFileCommunication);
                abstractPcapCommunications.Add(writeCompleteCommunication);
                abstractPcapCommunications.Add(finalCommnication);
                UpgradeOperation upgradeOperation = new UpgradeOperation(abstractPcapCommunications);
                Dispatcher.CurrentDispatcher.Invoke(async () =>
                {
                    var dic= await upgradeOperation.GetOperationResult();
                    DispalyResult(dic, equ.Mac, "升级操作成功！", "升级失败！", 3);
                });
            }
            AbstractPcapCommunication<bool> CommunicationFactory(string type,PhysicalAddress physicalAddress,string password,ILiveDevice device)
            {
                switch (type)
                {
                    case "0":
                        return new UpgradeVendorCommunication(physicalAddress, password, device);
                    case "1":
                        return new UpgradeImageCommunication(physicalAddress, password, device);
                    case "2":
                        return new UpgradeBootCommunicaition(physicalAddress, password, device);
                    default:
                        return new UpgradeVendorCommunication(physicalAddress, password, device);
                }
            }


        }
        [RelayCommand]
        public void HandleRestore(int id)
        {
            Loading = true;
            var equ=GetEntityById(id);
            RestoreCommunication restoreCommunication=new RestoreCommunication(PhysicalAddress.Parse(equ.Mac),Password,SelectDevice);
            PcapOperation<bool> operation=new PcapOperation<bool>(restoreCommunication);
            Dispatcher.CurrentDispatcher.Invoke(async () =>
            {
                var dic = await operation.GetOperationResult();
                DispalyResult(dic, equ.Mac, "恢复出厂设置成功！", "恢复出厂设置失败！");
            });
        }
        [RelayCommand]
        public void HandleSaveConfig(int id)
        {
            Loading = true;
            var equ = GetEntityById(id);
            SaveConfigCommunication saveConfigCommunication = new SaveConfigCommunication(PhysicalAddress.Parse(equ.Mac), Password, SelectDevice);
            PcapOperation<bool> operation = new PcapOperation<bool>(saveConfigCommunication);
            Dispatcher.CurrentDispatcher.Invoke(async () =>
            {
                Dictionary<int, List<bool>>? dic = await operation.GetOperationResult();
                DispalyResult(dic, equ.Mac, "保存配置成功", "保存配置失败！");
            });
        }
        private async void DispalyResult(Dictionary<int, List<bool>>? dic,string mac,string successMsg,string failMsg,int index=0)
        {
            if (dic == null)
            {
                Growl.Error("设备连接失败！请检查设备或者连接密码是否正确！");
            }
            else
            {
                if(dic.TryGetValue(index,out var result))
                {
                    if (result.Any(t => t == true))
                    {
                        await baseService.UpdateExpressionAsync(t=>t.Mac==mac,t=>t.Description==successMsg);
                        Growl.Success(successMsg);
                    }
                    else
                    {
                        await baseService.UpdateExpressionAsync(t => t.Mac == mac, t => t.Description == failMsg);
                        Growl.Error(failMsg);
                    }
                }
                else
                {
                    Growl.Error("操作设备异常!通讯中部分环节发生异常，通讯终止！");
                }
            }
            Loading = false;
            
        }
        [RelayCommand]
        public void HandleBatchEditIp()
        {
            GetSelectedValue();
            OpenCurrentPageDialog(typeof(EditNetworkForm));
        }
        [RelayCommand]
        public void BatchSaveIp()
        {
            if(ipHelper.ValidateIPAddress(StartIP) && ipHelper.GetIpType(StartIP) == 2)
            {
                string startIp = StartIP;
                BatchOperation("请选择需要修改ip的设备！", "将按照左边设备列表的顺序分配连续IP(可拖动排序),是否确认？", equ =>
                {
                    equ.Ip = startIp;
                    EditNetworkInfoCommunication editNetworkInfo = new EditNetworkInfoCommunication(PhysicalAddress.Parse(equ.Mac), Password, SelectDevice) { EquInfo = equ };
                    PcapOperation<bool> operation = new PcapOperation<bool>(editNetworkInfo);
                    List<string> ips = ipHelper.GetContinuousIP(startIp, 1, 1, ipaddress => ipaddress.GetAddressBytes().Last() == 0 || ipaddress.GetAddressBytes().Last() == 255);
                    startIp = ips.First();
                    return operation;
                }, 0, t => t == true, async dic =>
                {
                    foreach (string key in dic.Keys)
                    {
                        if (dic[key])
                        {
                            var equ = UpgradeList.FirstOrDefault(t => t.Mac == key);
                            await baseService.UpdateExpressionAsync(t => t.Mac == key, t => t.Ip == equ.Ip,t=>t.Description== "修改ip成功！");
                        }
                        else
                        {
                            await baseService.UpdateExpressionAsync(t => t.Mac == key, t => t.Description == "修改ip失败！");
                        }
                    }
                });
            }
            else
            {
                Growl.Error("ip不正确！");
            }
            
        }
        [RelayCommand]
        public void BatchRestart()
        {
            GetSelectedValue();
            BatchOperation("请选择需要重启的设备！", "将批量重启设备,是否确认？", equ =>
            {
                RestartCommunication restartCommunication = new RestartCommunication(PhysicalAddress.Parse(equ.Mac), Password, SelectDevice);
                PcapOperation<bool> operation = new PcapOperation<bool>(restartCommunication);
                return operation;
            }, 0, t => t == true, async dic =>
            {
                foreach (string key in dic.Keys)
                {
                    string status = dic[key] ? "重启成功" : "重启失败";
                    await baseService.UpdateExpressionAsync(t => t.Mac == key, t => t.Description == status);
                }
            });
        }
        [RelayCommand]
        public void BatchUpdate(string type)
        {
            AbstractPcapCommunication<bool> CommunicationFactory(string type, PhysicalAddress physicalAddress, string password, ILiveDevice device)
            {
                switch (type)
                {
                    case "0":
                        return new UpgradeVendorCommunication(physicalAddress, password, device);
                    case "1":
                        return new UpgradeImageCommunication(physicalAddress, password, device);
                    case "2":
                        return new UpgradeBootCommunicaition(physicalAddress, password, device);
                    default:
                        return new UpgradeVendorCommunication(physicalAddress, password, device);
                }
            }
            BatchOperation("请选择需要升级的设备！", "即将批量升级设备耗时较长，期间不能操作，是否确认？", equ =>
            {
                List<AbstractPcapCommunication<bool>> abstractPcapCommunications = [];
                PhysicalAddress macAdress = PhysicalAddress.Parse(equ.Mac);
                AbstractPcapCommunication<bool> writeCommunication = new WriteCommnuication(macAdress, Password, SelectDevice);
                AbstractPcapCommunication<bool> writeFileCommunication = new WriteFileCommunication(UpgradeFile, macAdress, Password, SelectDevice);
                AbstractPcapCommunication<bool> writeCompleteCommunication = new WriteCompleteCommunication(UpgradeFile, macAdress, Password, SelectDevice);
                AbstractPcapCommunication<bool> finalCommnication = CommunicationFactory(type, macAdress, Password, SelectDevice);
                abstractPcapCommunications.Add(writeCommunication);
                abstractPcapCommunications.Add(writeFileCommunication);
                abstractPcapCommunications.Add(writeCompleteCommunication);
                abstractPcapCommunications.Add(finalCommnication);
                UpgradeOperation upgradeOperation = new UpgradeOperation(abstractPcapCommunications);
                return upgradeOperation;
            }, 3, t => t == true, async dic =>
            {
                string des;
                if (type == "0")
                {
                    des = "Vendor";
                }else if (type == "1")
                {
                    des = "image";
                }else
                {
                    des = "boot";
                }
                foreach (string key in dic.Keys)
                {
                    string status;
                    if (dic[key])
                    {
                        status = "成功";
                    }
                    else
                    {
                        status = "失败";
                    }
                    string message = $"{des}升级{status}!";
                    await baseService.UpdateExpressionAsync(t => t.Mac == key, t => t.Description == message);
                }
            });

        }
        [RelayCommand]
        public void BatchRestore()
        {
            GetSelectedValue();
            BatchOperation("请选择需要恢复出厂设置的设备！", "即将批量恢复设备出厂配置，是否确认？", equ =>
            {
                RestartCommunication restartCommunication = new RestartCommunication(PhysicalAddress.Parse(equ.Mac), Password, SelectDevice);
                return new PcapOperation<bool>(restartCommunication);
            }, 0, t => t == true, async dic =>
            {
                foreach (string key in dic.Keys)
                {
                    if (dic[key])
                    {
                        await baseService.UpdateExpressionAsync(t => t.Mac == key, t => t.Description == "恢复出厂设置成功！");
                    }
                    else
                    {
                        await baseService.UpdateExpressionAsync(t => t.Mac == key, t => t.Description == "恢复出厂设置失败！");
                    }
                }
            });
        }
        /// <summary>
        /// 执行批量操作命令
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="errorMsg">错误提示</param>
        /// <param name="confirmMsg">确认提示</param>
        /// <param name="func">生成communication的方法</param>
        /// <param name="finalResultIndex">最终结果的索引</param>
        /// <param name="trueCondition">判断返回结果是true的表达式</param>
        /// <param name="action">获取全部结果后的操作</param>
        private void BatchOperation<T>(string errorMsg,string confirmMsg,Func<EquInfo, PcapOperation<T>> func,int finalResultIndex,Func<T,bool> trueCondition,Action<Dictionary<string,bool>> action)
        {
            if (string.IsNullOrEmpty(Password))
            {
                Growl.Error("请先输入通讯密码！");
                return;
            }
            if(SelectDevice == null)
            {
                Growl.Error("请先选择网卡！");
                return;
            }
            if (UpgradeList.Count > 0)
            {
                Loading = true;
                var result = HandyControl.Controls.MessageBox.Show(confirmMsg, "操作确认", MessageBoxButton.YesNo, MessageBoxImage.Question);
                if (result == MessageBoxResult.Yes)
                {
                    Loading = true;
                    List<PcapOperation<T>> operations = [];
                    foreach (var item in UpgradeList)
                    {
                        PcapOperation<T> pcapOperation = func(item);
                        operations.Add(pcapOperation);
                    }
                    BatchOperation<T> batchOperation = new BatchOperation<T>(finalResultIndex, trueCondition, [.. operations]);
                    Dispatcher.CurrentDispatcher.Invoke(async () =>
                    {
                        var result = await batchOperation.GetOperationResult();
                        action.Invoke(result);
                        Loading = false;
                        GetList();
                        Growl.Success("操作完成！");
                    });
                }
            }
            else
            {
                Growl.Error(errorMsg);
            }
        }

        private void GetSelectedValue()
        {
            this.UpgradeList.Clear();
            SelectedValues.ForEach(t => UpgradeList.Add(t));
        }
        [RelayCommand]
        public void EditNetInfo()
        {
            string ip = "192.168.1.1";
            var r= ipHelper.IpToUInt(ip);
            var ip1 = ipHelper.UintToIpString(r);
            var r1 = ipHelper.GetIpType(ip);
            var r2= ipHelper.LongToIpString((long)r);
            var r3 = ipHelper.IpToLong(ip);
            var netmask = "255.255.255.192";
            var isNetMask = ipHelper.IsNetMask(netmask);
            var ipList = ipHelper.GetContinuousIP("192.168.1.1", 255, 1, (ip) =>
            {
                var bytes = ip.GetAddressBytes();
                return bytes[3] == 0 || bytes[3] == 255;
            });
            //EditNetworkInfoCommunication editNetworkInfoCommunication = new EditNetworkInfoCommunication(PhysicalAddress.Parse("60-63-fd-83-e8-94"), "tscchina", SelectDevice)
            //{
            //    EquInfo = new EquInfo()
            //    {
            //        Ip = "192.168.1.15",
            //        Mask = "255.255.255.128",
            //        GateWay = "0.0.0.0",
            //        Vlan = 1
            //    }
            //};
            //RestartCommunication restartCommunication = new RestartCommunication(PhysicalAddress.Parse("60-63-fd-83-e8-94"), "tscchina", SelectDevice);
            //PcapOperation<bool> pcapOperation = new PcapOperation<bool>(editNetworkInfoCommunication);
            //UpgradeOperation upgradeOperation = new UpgradeOperation(new System.IO.FileInfo("D:/code/NetCard-0.02\\upgradeFile\\1.3.6.1.4.1.36971.1.1.2016.1\\RD156_R8391001_36971.1.1.2016.1_Hollysys_GM010-ISW-24L-24TX2GC_defaultcfg_1.0_oem-encrypt.bin"), PhysicalAddress.Parse("60-63-fd-83-e8-94"), "tscchina", SelectDevice);
            //Dispatcher.CurrentDispatcher.Invoke(async () =>
            //{
            //    Stopwatch stopwatch = Stopwatch.StartNew();
            //    await upgradeOperation.GetUpgradeResult();
            //    //var result = await pcapOperation.GetOperationResult();
            //    stopwatch.Stop();
            //    int i = 1;
            //    //SearchEqu();
            //});
        }

        public override string DialogToken => "EquInfoPage";

        public override EquInfo GetEntityById(int primaryKey)
        {
            return baseService.Find(t => t.Id == primaryKey);
        }

        public override (Expression<Func<EquInfo, object>>, OrderByType)? GetOrderByExpression()
        {
            return (t => t.Id, OrderByType.Desc);
        }

        public override Expression<Func<EquInfo, bool>> GetQueryExpression()
        {
            if (Query != null)
            {
                var exp = Expressionable.Create<EquInfo>()
                    .AndIF(!string.IsNullOrEmpty(Query.SN), t => t.SN.Contains(Query.SN!))
                    .AndIF(!string.IsNullOrEmpty(Query.Mac), t => t.Mac.Contains(Query.Mac!))
                    .AndIF(!string.IsNullOrEmpty(Query.Ip), t => t.Ip.Contains(Query.Ip!))
                    .AndIF(!string.IsNullOrEmpty(Query.GateWay), t => t.GateWay.Contains(Query.GateWay!))
                    .AndIF(!string.IsNullOrEmpty(Query.Mask), t => t.Mask.Contains(Query.Mask!))
                    .AndIF(Query.Vlan != null, t => t.Vlan == Query.Vlan)
                    .AndIF(!string.IsNullOrEmpty(Query.BootVersion), t => t.BootVersion.Contains(Query.BootVersion!))
                    .AndIF(!string.IsNullOrEmpty(Query.ImageVersion), t => t.ImageVersion.Contains(Query.ImageVersion!))
                    .AndIF(!string.IsNullOrEmpty(Query.VendorVersion), t => t.VendorVersion.Contains(Query.VendorVersion!))
                    .AndIF(!string.IsNullOrEmpty(Query.HardwareVersion), t => t.HardwareVersion.Contains(Query.HardwareVersion!))
                    .AndIF(!string.IsNullOrEmpty(Query.ProductLine), t => t.ProductLine.Contains(Query.ProductLine!))
                    .AndIF(!string.IsNullOrEmpty(Query.TypeId), t => t.TypeId.Contains(Query.TypeId!))
                    .AndIF(!string.IsNullOrEmpty(Query.Oid), t => t.Oid.Contains(Query.Oid!));
                return exp.ToExpression();
            }
            else
            {
                return t => true;
            }
        }
    }
}
